import asyncio
import websockets
import json
import threading

# 存储所有客户端
Clients = []

# 服务端
class WS_Server():
    def __init__(self):
        self.ip = "127.0.0.1"
        self.port = 9090
 
    # 发送消息
    async def sendMsg(self, websocket, msg):
        if websocket != None:
           await websocket.send(msg)
        else:
            self.broadcast(msg)
        await asyncio.sleep(0.2)
 
 
    # 群发消息
    async def broadcast(self, msg):
        for user in Clients:
           await user['socket'].send(msg)
 
 
    # 连接一个客户端，起一个循环监听
    async def echo(self, websocket, path):
        # 握手
        client_ip, client_port = websocket.remote_address
        print(f"连接到:{client_ip}:{client_port}")
        await websocket.send(json.dumps({"stat": "success"}))
        # 循环监听
        while True:
            try:
                recv_text = await websocket.recv()
                message = "收到消息: {}".format(recv_text)
                await websocket.send(message)
                data = json.loads(recv_text)
                receiver = data['to']
                content = data['content']
                sender = data['from']
                stat = data['stat']
                if stat == "link":
                    checked = False
                    if len(Clients) > 0 :
                        for usr in Clients:
                            if usr['name'] == sender:
                                checked = True
                                break
                        if checked:
                            print(f"{client_ip}:{client_port}不能被重复关联")
                        else:
                            Clients.append({"socket": websocket, "name": sender})
                            print(f"{sender} 已关联 {client_ip}:{client_port}")
                    else:
                        Clients.append({"socket": websocket, "name": sender})
                        print(f"{sender} 已关联 {client_ip}:{client_port}")
                else:
                    msg = json.dumps({"stat": stat, "to": receiver, "content": content, "from": sender})
                    if receiver == "":
                        await self.broadcast(msg)
                        print('消息已群发')
                    else:
                        checked1 = False
                        for usr in Clients:
                            if usr['name'] == receiver:
                                socket = usr['socket']
                                await self.sendMsg(socket, msg)
                                checked1 = True
                                break
                        if checked1:
                            print(f"已给{receiver}发送消息")
                        else:
                            print(f"发送失败，未找到{receiver}")
 
            except websockets.ConnectionClosed:
                print(f"从{client_ip}:{client_port}断开连接")
                break
            except websockets.InvalidState:
                print("无效状态")
                break
            except Exception as e:
                print("ws连接报错", e)
                break
 
    # 启动服务器
    async def runServer(self):
        async with websockets.serve(self.echo, self.ip, self.port):
            await asyncio.Future()  # run forever
 
	# 多协程模式，防止阻塞主线程无法做其他事情
    def WebSocketServer(self):
        asyncio.run(self.runServer())
 
    # 多线程启动
    def startServer(self):
        # 多线程启动，否则会堵塞
        thread = threading.Thread(target=self.WebSocketServer)
        thread.start()
        # thread.join()
 
 
if __name__=='__main__':
    s = WS_Server()
    s.startServer()
    print("ws服务已启动")